package my.projects.jandan.test;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.Header;
import org.apache.http.HeaderIterator;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 * 
 * @author Mr.He
 * 
 */
public class HttpClientUtils {
    private static final String LOGIN_URL = "https://72.52.124.215/logging.php?action=login";

    private static String cdb_sid = "";

    private static String formhash = "";

    public static void main(String[] args) throws Exception {

        sendSSLPostRequest(LOGIN_URL);
        // sendSSLPostRequest("https://72.52.124.215/forumdisplay.php?fid=37", null);
    }

    /**
     * 向HTTPS地址发送POST请求
     * 
     * @param reqURL 请求地址
     * @param params 请求参数
     * @return 响应内容
     */
    @SuppressWarnings("finally")
    public static String sendSSLPostRequest(String reqURL) {

        long responseLength = 0; // 响应长度

        String responseContent = null; // 响应内容

        HttpClient httpClient = new DefaultHttpClient(); // 创建默认的httpClient实例

        httpClient
                .getParams()
                .setParameter("Accept", "text/html, application/xhtml+xml, */*")
                .setParameter(CoreProtocolPNames.USER_AGENT,
                        "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)")
                .setParameter("UA-CPU", "AMD64").setParameter("Accept-Encoding", "gzip, deflate")
                .setParameter("Accept-Language", "zh-CN")
                .setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "GBK");


        httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY,
                CookiePolicy.BROWSER_COMPATIBILITY); // 设置cookie的兼容性

        // 创建TrustManager
        X509TrustManager xtm = new X509TrustManager() {
            public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
                    throws CertificateException {}

            public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
                    throws CertificateException {}

            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        // 这个好像是HOST验证
        X509HostnameVerifier hostnameVerifier = new X509HostnameVerifier() {
            public boolean verify(String arg0, javax.net.ssl.SSLSession arg1) {
                return true;
            }

            public void verify(String arg0, javax.net.ssl.SSLSocket arg1) throws IOException {}

            public void verify(String arg0, String[] arg1, String[] arg2) throws SSLException {}

            public void verify(String arg0, X509Certificate arg1) throws SSLException {}
        };

        try {
            // TLS1.0与SSL3.0基本上没有太大的差别，可粗略理解为TLS是SSL的继承者，但它们使用的是相同的SSLContext
            SSLContext ctx = SSLContext.getInstance("TLS");

            // 使用TrustManager来初始化该上下文，TrustManager只是被SSL的Socket所使用
            ctx.init(null, new TrustManager[] {xtm}, null);

            // 创建SSLSocketFactory
            SSLSocketFactory socketFactory = new SSLSocketFactory(ctx);

            // 去除host验证
            socketFactory.setHostnameVerifier(hostnameVerifier);

            // 通过SchemeRegistry将SSLSocketFactory注册到我们的HttpClient上
            httpClient.getConnectionManager().getSchemeRegistry()
                    .register(new Scheme("https", 443, socketFactory));


            // 链接首页，获取cookie cdb_sid值-----------------------------------------------------------


            homePageVisit(httpClient);


            // 链接登陆页，获取登陆页html标签，分析隐藏域获取"formhash"值，未登陆做好准备，进一步获取cbd_sid值

            loginPageVisit(httpClient);

            // 发起登陆请求---------------------------------------------------------------------------


            responseContent = login(reqURL, responseContent, httpClient);

            System.out.println(responseContent);
            /*
             * FileWriter fw = null; File f = new File("D:\\电驴.html");
             * 
             * try { if(!f.exists()){ f.createNewFile(); } fw = new FileWriter(f); BufferedWriter
             * out = new BufferedWriter(fw); out.write(responseContent, 0,
             * responseContent.length()-1); out.close();
             * System.out.println("end====================="); } catch (IOException e) {
             * e.printStackTrace(); }
             */
            /*
             * FileOutputStream o = new FileOutputStream("D:\\电驴2.html");
             * o.write(responseContent.getBytes("GBK")); o.close();
             */

        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpClient.getConnectionManager().shutdown(); // 关闭连接,释放资源
            return responseContent;
        }
    }

    /**
     * 登陆
     * 
     * @param reqURL
     * @param responseContent
     * @param httpClient
     * @return
     * @throws UnsupportedEncodingException
     * @throws IOException
     * @throws ClientProtocolException
     */
    private static String login(String reqURL, String responseContent, HttpClient httpClient)
            throws UnsupportedEncodingException, IOException, ClientProtocolException {
        long responseLength;
        Map<String, String> params = new HashMap<String, String>();
        // params.put("formhash", formhash);
        params.put("formhash", "334389dc");
        params.put("referer", "index.php");
        params.put("loginfield", "username");
        params.put("username", "qsyz");
        params.put("password", "821020");
        params.put("questionid", "0");
        params.put("answer", "");
        params.put("cookietime", "315360000");
        params.put("loginmode", "");
        // params.put("action", "login");
        params.put("styleid", "");
        params.put("loginsubmit", "true");


        HttpPost httpPost = new HttpPost(reqURL); // 创建HttpPost
        httpPost.setHeader("Accept-Encoding", "gzip, deflate");
        httpPost.setHeader("referer", "https://72.52.124.215/index.php");
        httpPost.setHeader("cdb_sid", cdb_sid);

        if (params != null) {
            List<NameValuePair> formParams = new ArrayList<NameValuePair>(); // 构建POST请求的表单参数
            for (Map.Entry<String, String> entry : params.entrySet()) {
                formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(formParams, "UTF-8"));
        }

        HttpResponse response = httpClient.execute(httpPost); // 执行POST请求
        HttpEntity entity = response.getEntity(); // 获取响应实体

        // 获取登录返回的Cookie==============================================================================
        Header[] hs = response.getHeaders("Set-Cookie");
        for (Header header : hs) {
            System.out.println("响应头cookies================" + header);
        }

        HeaderIterator it = response.headerIterator("Set-Cookie");
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        // =============================================================================================

        if (null != entity) {
            responseLength = entity.getContentLength();
            responseContent = EntityUtils.toString(new GzipDecompressingEntity(entity), "GBK");
            EntityUtils.consume(entity); // Consume response content
        }
        // System.out.println("请求地址: " + httpPost.getURI());
        // System.out.println("响应状态: " + response.getStatusLine());
        // System.out.println("响应长度: " + responseLength);
        System.out.println("响应内容: " + responseContent);
        return responseContent;
    }

    /**
     * 访问登陆页
     * 
     * @param httpClient
     * @throws IOException
     * @throws ClientProtocolException
     */
    private static void loginPageVisit(HttpClient httpClient) throws IOException,
            ClientProtocolException {


        HttpGet loginPageGet = new HttpGet("https://72.52.124.215/logging.php?action=login");

        loginPageGet.addHeader("cdb_sid", cdb_sid);
        loginPageGet.addHeader("referer", "https://72.52.124.215/index.php");

        try {
            HttpResponse loginPageResponse = httpClient.execute(loginPageGet);

            HttpEntity loginPageEntity = loginPageResponse.getEntity();

            String loginHtml = EntityUtils.toString(loginPageEntity, "GBK");

            Document doc = Jsoup.parse(loginHtml);

            Element input = doc.select("form").first().select("input").first();

            formhash = input.attr("value");

            System.out.println("formhash========================" + formhash);

            Header[] hs = loginPageResponse.getHeaders("Set-Cookie");

            for (Header header : hs) {

                if (header.getName().equals("cdb_sid")) {
                    cdb_sid = header.getValue();
                    System.out.println("登陆页sid赋值====================");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            loginPageGet.abort();
        }

    }

    /**
     * 访问首页 获取cookie cbd_sid
     * 
     * @param httpClient
     * @throws IOException
     * @throws ClientProtocolException
     */
    private static void homePageVisit(HttpClient httpClient) throws IOException,
            ClientProtocolException {
        HttpGet get = new HttpGet("https://72.52.124.215");

        HttpResponse indexResponse = httpClient.execute(get);

        try {
            /*
             * HeaderIterator it = indexResponse.headerIterator("Set-Cookie");
             * 
             * while (it.hasNext()) { System.out.println("进入首页获取cookie 成功==" +
             * it.next().toString()); }
             */

            Header[] hs = indexResponse.getHeaders("Set-Cookie");
            for (Header header : hs) {
                if (header.getName().equals("cdb_sid")) {
                    cdb_sid = header.getValue();
                    System.out.println("获取到sid并赋值====================");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            get.abort();
        }
    }
}
